package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.dto.SkuDTO;
import com.leyou.common.dto.SpuDTO;
import com.leyou.common.dto.SpuDetailDTO;
import com.leyou.common.entity.Category;
import com.leyou.common.exception.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {

@Autowired
private BrandService brandService;

@Autowired
private CategoryService categoryService;

@Autowired
private SpuService spuService;

@Autowired
private SpuDetailService spuDetailService;

@Autowired
private SkuService skuService;

@Autowired
private AmqpTemplate amqpTemplate;




    @Override
    public PageDTO<SpuDTO> querySpuPage(Integer page, Integer rows, Boolean saleable, Integer cid, Integer bid, Integer sid) {
        page = Math.max(page, 1);
        rows = Math.min(rows, 100);

        Page<Spu> result = query()
                .eq(saleable != null, "saleable", saleable)
                .eq(bid != null, "brand_id", bid)
                .eq(cid != null, "cid3", cid)
                .eq(sid != null, "id", sid)
                .page(new Page<Spu>(page, rows));

        List<Spu> records = result.getRecords();
        long total = result.getTotal();
        long pages = result.getPages();
        List<SpuDTO> spuDTOS = SpuDTO.convertEntityList(records);
        for (SpuDTO spuDTO : spuDTOS) {
            // 查询spu的分类和品牌的名称
            handleCategoryAndBrandName(spuDTO);
        }
        return new PageDTO<>(total, pages, spuDTOS);
    }

    @Override
    public void saveGoods(SpuDTO spuDTO) {
        try {
            Spu spu = spuDTO.toEntity(Spu.class);

            boolean save = spuService.save(spu);
            SpuDetailDTO spuDetail = spuDTO.getSpuDetail();
            spuDetail.setSpuId(spu.getId());
            List<SkuDTO> skus = spuDTO.getSkus();
            spuDetailService.save(spuDetail.toEntity(SpuDetail.class));
            skuService.saveBatch(
                    skus.stream().map(skuDTO -> {
                        Sku sku = skuDTO.toEntity(Sku.class);
                        sku.setSpuId(spu.getId());
                        return sku;
                    }).collect(Collectors.toList())
            );
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("新增商品失败");
        }
    }

    @Override
    public void updateSaleable(Integer id, Boolean saleable) {
        try {
            spuService.update().eq("id", id).set("saleable", saleable).update();
            skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        } catch (Exception e) {
            e.printStackTrace();
            throw new LyException(500, "商品上下架修改失败");
        }
        String rotingKey = saleable? MQConstants.RoutingKeyConstants.ITEM_UP_KEY: MQConstants.RoutingKeyConstants.ITEM_DOWN_KEY;
        amqpTemplate.convertAndSend("jhj", rotingKey, id);
    }

    @Override
    public ResponseEntity<SpuDTO> querySpuSkuSpuDetail(Integer id) {
        Spu spu = spuService.getById(id);
        List<Sku> list = skuService.list(new QueryWrapper<Sku>().eq("spu_id", id));
        List<SkuDTO> skuDTOS = SkuDTO.convertEntityList(list);
        SpuDetail spudetail = spuDetailService.getOne(new QueryWrapper<SpuDetail>().eq("spu_id", id));
        SpuDTO spuDTO = new SpuDTO(spu);
        spuDTO.setSpuDetail(new SpuDetailDTO(spudetail));
        spuDTO.setSkus(skuDTOS);
        return ResponseEntity.ok().body(spuDTO);
    }

    @Override
    @Transactional
    public void updateMyGoods(SpuDTO spuDTO) {
        Spu spu = spuDTO.toEntity(Spu.class);
        if(spu != null){
            boolean success = spuService.saveOrUpdate(spu);
            if (!success){
                throw new LyException(500, "更新失败");
            }
        }

        SpuDetailDTO spuDetail = spuDTO.getSpuDetail();
        if (spuDetail != null){
            boolean success = spuDetailService.update(spuDetail.toEntity(SpuDetail.class),new QueryWrapper<SpuDetail>().eq("spu_id", spuDetail.getSpuId()));
            if(!success){
                throw new LyException(500, "商品更新失败");
            }
        }

        Map<Boolean, List<Sku>> map = spuDTO.getSkus()
                .stream()
                .map(skuDTO -> skuDTO
                        .toEntity(Sku.class))
                .collect(Collectors.groupingBy(sku -> sku
                        .getSaleable() == null));

        List<Sku> updateSku = map.get(true);
        if(updateSku != null){
            boolean suceess = skuService.saveOrUpdateBatch(updateSku);
            if(!suceess){
                throw new LyException(500, "更新商品失败");
            }
        }

        List<Sku> deleteSku = map.get(false);
        if(deleteSku != null){
            boolean success = skuService.removeByIds(deleteSku.stream().map(sku -> sku.getId()).collect(Collectors.toList()));
            if(!success){
                throw new LyException(500,"更新失败");
            }
        }
    }

    @Override
    public SpuDTO getBySpuId(Integer id) {
        Spu spu = spuService.getById(id);
        return new SpuDTO(spu);
    }

    private void handleCategoryAndBrandName(SpuDTO spuDTO) {
        Brand brand = brandService.getById(spuDTO.getBrandId());
        if(brand != null) {
            spuDTO.setBrandName(brand.getName());
        }

        List<Category> categories = categoryService.listByIds(spuDTO.getCategoryIds());
        if(!CollectionUtils.isEmpty(categories)) {
            // 取出分类的名称，拼接起来
            String names = categories.stream().map(Category::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(names);
        }
    }
}
